package com.bamboo.tool.template.torna.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.torna.sdk.param.*;
import com.bamboo.tool.entity.ApiMethod;
import com.bamboo.tool.entity.JavaFieldInfo;
import com.bamboo.tool.entity.MethodOtherInfo;
import com.bamboo.tool.enums.DataType;
import com.bamboo.tool.enums.DescType;
import com.bamboo.tool.enums.JavaDataType;
import com.bamboo.tool.util.DescProcessUtil;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author bamboo
 * Date 2022/9/29 10:50
 * Description RestfulCloud转换torna工具类
 */
public class RestfulCloudToTornaUtil {

    public static DocItem methodToDocItemConversion(ApiMethod method, List<String> allDescDort) {
        DocItem methodDoc = new DocItem();
        Set<String> requestMethods = method.getRequestMethods();
        MethodOtherInfo otherInfo = method.getOtherInfo();
        methodDoc.setHttpMethod(StrUtil.join(",", requestMethods));
        methodDoc.setAuthor(otherInfo.getAuthor());
        methodDoc.setName(DescProcessUtil.getMethodDesc(method, allDescDort));
        methodDoc.setUrl(method.getMethodUrl());
        methodDoc.setContentType(otherInfo.getContentType());
        methodDoc.setDeprecated(otherInfo.isDeprecated() ? "该接口已废弃" : null);

        List<DocParamPath> pathParams = otherInfo.getPathParams().stream().map(e -> javaFieldInfoToDocParamPathReq(e, allDescDort)).collect(Collectors.toList());
        List<DocParamHeader> headParams = otherInfo.getHeadParams().stream().map(e -> javaFieldInfoToDocParamHeaderReq(e, allDescDort)).collect(Collectors.toList());
        List<DocParamReq> queryParams = otherInfo.getQueryParams().stream().map(e -> javaFieldInfoToDocParamReq(e, allDescDort)).collect(Collectors.toList());
        Map<String, String> heads = otherInfo.getHeads();
        if (CollUtil.isNotEmpty(heads)) {
            heads.forEach((key, value) -> {
                DocParamHeader paramHeader = new DocParamHeader();
                paramHeader.setName(key);
                paramHeader.setExample(value);
                paramHeader.setRequired((byte) 1);
                headParams.add(paramHeader);
            });
        }
        List<DocParamReq> bodyParams = new ArrayList<>();
        List<JavaFieldInfo> bambooBodyParams = new ArrayList<>();
        if (otherInfo.getBodyParams().size() == 1) {
            JavaFieldInfo javaFieldInfo = otherInfo.getBodyParams().get(0);
            DataType fieldType = javaFieldInfo.getFieldType();
            DataType arrayType = javaFieldInfo.getArrayType();
            if (arrayType != null) {
                methodDoc.setIsRequestArray((byte) 1);
                methodDoc.setRequestArrayType(fieldType.getCode());
                bodyParams = javaFieldInfo.getChildren().stream().map(e -> javaFieldInfoToDocParamReq(e, allDescDort)).collect(Collectors.toList());
            } else {
                otherInfo.getBodyParams().stream().forEach(e -> {
                    if (CollUtil.isNotEmpty(e.getChildren())) {
                        bambooBodyParams.addAll(e.getChildren());
                    } else {
                        bambooBodyParams.add(e);
                    }
                });
            }
        } else {
            otherInfo.getBodyParams().stream().forEach(e -> {
                if (CollUtil.isNotEmpty(e.getChildren())) {
                    bambooBodyParams.addAll(e.getChildren());
                } else {
                    bambooBodyParams.add(e);
                }
            });
        }
        List<DocParamReq> collect = bambooBodyParams.stream().map(e -> javaFieldInfoToDocParamReq(e, allDescDort)).collect(Collectors.toList());

        bodyParams.addAll(collect);
        JavaFieldInfo responseParam = otherInfo.getResponseParam();
        DataType fieldType = responseParam.getFieldType();
        DataType arrayType = responseParam.getArrayType();
        List<JavaFieldInfo> children = responseParam.getChildren();
        if (!fieldType.equals(DataType.VOID)) {
            if (DataType.LIST.equals(arrayType) || DataType.SET.equals(arrayType)) {
                methodDoc.setIsResponseArray((byte) 1);
                methodDoc.setResponseArrayType(fieldType.getCode());
            }
            List<DocParamResp> resps = children.stream().map(e -> javaFieldInfoToDocParamResp(e, allDescDort)).collect(Collectors.toList());
            methodDoc.setResponseParams(resps);
        }

        methodDoc.setPathParams(pathParams);
        methodDoc.setHeaderParams(headParams);
        methodDoc.setQueryParams(queryParams);
        methodDoc.setRequestParams(bodyParams);
        Map<String, String> desc = method.getDesc();
        if (CollUtil.isNotEmpty(desc)) {
            String apiNote = desc.get(DescType.API_NOTE.getCode());
            String javaDoc = desc.get(DescType.JAVA_DOC.getCode());
            if (StrUtil.isEmpty(apiNote)) {
                methodDoc.setDescription(javaDoc);
            } else {
                methodDoc.setDescription(apiNote);
            }
        }

        return methodDoc;
    }

    public static DocParamReq javaFieldInfoToDocParamReq(JavaFieldInfo fieldInfo, List<String> allDescDort) {
        DataType fieldType = fieldInfo.getFieldType();
        DataType arrayType = fieldInfo.getArrayType();
        String fieldName = fieldInfo.getFieldName();
        String javaFieldDesc = DescProcessUtil.getDesc(allDescDort, fieldInfo.getDesc());
        DocParamReq docParamReq = new DocParamReq();
        docParamReq.setName(fieldName);
        if (DataType.LIST.equals(arrayType) || DataType.SET.equals(arrayType)) {
            docParamReq.setType("array[" + fieldInfo.getArrayType() + "]");
        } else if (DataType.ARRAY.equals(arrayType)) {
            docParamReq.setType(fieldInfo.getArrayType() + "[]");
        } else {
            docParamReq.setType(fieldType.getCode());
        }
        docParamReq.setRequired((byte) (fieldInfo.isRequired() ? 1 : 0));
        docParamReq.setDescription(javaFieldDesc);
        docParamReq.setMaxLength(fieldInfo.getMaxLength());
        if (fieldInfo.getExampleValue() == null && fieldInfo.getDefaultValue() != null) {
            docParamReq.setExample(fieldInfo.getDefaultValue().toString());
        }
        if (fieldInfo.getExampleValue() != null) {
            docParamReq.setExample(fieldInfo.getExampleValue().toString());
        }
        if (CollUtil.isNotEmpty(fieldInfo.getEnums())) {
            if (StrUtil.isNotBlank(javaFieldDesc)) {
                docParamReq.setDescription(javaFieldDesc + "<br/>" + CollUtil.join(fieldInfo.getEnums(), "<br/>"));
            } else {
                docParamReq.setDescription(CollUtil.join(fieldInfo.getEnums(), "<br/>"));
            }
        } else {
            docParamReq.setDescription(javaFieldDesc);
        }
        if (CollUtil.isNotEmpty(fieldInfo.getChildren())) {
            List<DocParamReq> childrens = new ArrayList<>();
            fieldInfo.getChildren().stream().forEach(e -> childrens.add(javaFieldInfoToDocParamReq(e, allDescDort)));
            docParamReq.setChildren(childrens);
        }
        return docParamReq;
    }

    public static DocParamResp javaFieldInfoToDocParamResp(JavaFieldInfo fieldInfo, List<String> allDescDort) {
        DataType fieldType = fieldInfo.getFieldType();
        DataType arrayType = fieldInfo.getArrayType();
        String javaFieldDesc = DescProcessUtil.getDesc(allDescDort, fieldInfo.getDesc());
        DocParamResp docParamResp = new DocParamResp();
        docParamResp.setName(fieldInfo.getFieldName());
        if (DataType.LIST.equals(arrayType) || DataType.SET.equals(arrayType)) {
            docParamResp.setType("array[" + fieldInfo.getArrayType() + "]");
        } else if (DataType.ARRAY.equals(arrayType)) {
            docParamResp.setType(fieldInfo.getArrayType() + "[]");
        } else {
            docParamResp.setType(fieldType.getCode());
        }
        docParamResp.setRequired((byte) (fieldInfo.isRequired() ? 1 : 0));
        docParamResp.setDescription(javaFieldDesc);
        docParamResp.setMaxLength(fieldInfo.getMaxLength());
        if (fieldInfo.getExampleValue() == null && fieldInfo.getDefaultValue() != null) {
            docParamResp.setExample(fieldInfo.getDefaultValue().toString());
        }
        if (fieldInfo.getExampleValue() != null) {
            docParamResp.setExample(fieldInfo.getExampleValue().toString());
        }
        if (CollUtil.isNotEmpty(fieldInfo.getEnums())) {
            if (StrUtil.isNotBlank(javaFieldDesc)) {
                docParamResp.setDescription(javaFieldDesc + "<br/>" + CollUtil.join(fieldInfo.getEnums(), "<br/>"));
            } else {
                docParamResp.setDescription(CollUtil.join(fieldInfo.getEnums(), "<br/>"));
            }
        } else {
            docParamResp.setDescription(javaFieldDesc);
        }
        if (CollUtil.isNotEmpty(fieldInfo.getChildren())) {
            List<DocParamResp> docParamResps = fieldInfo.getChildren().stream().map(e -> javaFieldInfoToDocParamResp(e, allDescDort)).collect(Collectors.toList());
            docParamResp.setChildren(docParamResps);
        }
        return docParamResp;
    }

    public static DocParamPath javaFieldInfoToDocParamPathReq(JavaFieldInfo fieldInfo, List<String> allDescDort) {
        DataType fieldType = fieldInfo.getFieldType();
        DataType arrayType = fieldInfo.getArrayType();
        String javaFieldDesc = DescProcessUtil.getDesc(allDescDort, fieldInfo.getDesc());
        DocParamPath paramPath = new DocParamPath();
        paramPath.setName(fieldInfo.getFieldName());
        if (DataType.LIST.equals(arrayType) || DataType.SET.equals(arrayType)) {
            paramPath.setType("array[" + fieldInfo.getArrayType() + "]");
        } else if (DataType.ARRAY.equals(arrayType)) {
            paramPath.setType(fieldInfo.getArrayType() + "[]");
        } else {
            paramPath.setType(fieldType.getCode());
        }
        paramPath.setRequired((byte) (fieldInfo.isRequired() ? 1 : 0));
        if (CollUtil.isNotEmpty(fieldInfo.getEnums())) {
            if (StrUtil.isNotBlank(javaFieldDesc)) {
                paramPath.setDescription(javaFieldDesc + "<br/>" + CollUtil.join(fieldInfo.getEnums(), "<br/>"));
            } else {
                paramPath.setDescription(CollUtil.join(fieldInfo.getEnums(), "<br/>"));
            }
        } else {
            paramPath.setDescription(javaFieldDesc);
        }
        paramPath.setMaxLength(fieldInfo.getMaxLength());
        if (fieldInfo.getExampleValue() == null && fieldInfo.getDefaultValue() != null) {
            paramPath.setExample(fieldInfo.getDefaultValue().toString());
        }
        if (fieldInfo.getExampleValue() != null) {
            paramPath.setExample(fieldInfo.getExampleValue().toString());
        }
        return paramPath;
    }

    public static DocParamHeader javaFieldInfoToDocParamHeaderReq(JavaFieldInfo fieldInfo, List<String> allDescDort) {
        String javaFieldDesc = DescProcessUtil.getDesc(allDescDort, fieldInfo.getDesc());
        DocParamHeader paramHeader = new DocParamHeader();
        paramHeader.setName(fieldInfo.getFieldName());
        paramHeader.setRequired((byte) (fieldInfo.isRequired() ? 1 : 0));
        if (CollUtil.isNotEmpty(fieldInfo.getEnums())) {
            if (StrUtil.isNotBlank(javaFieldDesc)) {
                paramHeader.setDescription(javaFieldDesc + "<br/>" + CollUtil.join(fieldInfo.getEnums(), "<br/>"));
            } else {
                paramHeader.setDescription(CollUtil.join(fieldInfo.getEnums(), "<br/>"));
            }
        } else {
            paramHeader.setDescription(javaFieldDesc);
        }
        if (fieldInfo.getExampleValue() == null && fieldInfo.getDefaultValue() != null) {
            paramHeader.setExample(fieldInfo.getDefaultValue().toString());
        }
        if (fieldInfo.getExampleValue() != null) {
            paramHeader.setExample(fieldInfo.getExampleValue().toString());
        }
        return paramHeader;
    }

}
